// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.patent.service.impl;

import com.liuxinlong.api.WeChatMessageInterface;
import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.MessageContentTypeEnum;
import com.liuxinlong.enums.MessagePushBusinessEnum;
import com.liuxinlong.enums.PatentClassTypeEnum;
import com.liuxinlong.enums.PatentRiskLevelTypeEnum;
import com.liuxinlong.enums.ProjectLevelEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.enums.WorkflowTypeEnum;
import com.liuxinlong.modules.common.service.WorkFlowService;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.dao.PatentProposalDao;
import com.liuxinlong.modules.dao.PatentRiskDao;
import com.liuxinlong.modules.dao.ProjectDao;
import com.liuxinlong.modules.entity.MessageConfiguration;
import com.liuxinlong.modules.entity.PatentProposal;
import com.liuxinlong.modules.entity.PatentRisk;
import com.liuxinlong.modules.entity.Project;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.patent.dto.ImportPatentProposalDto;
import com.liuxinlong.modules.patent.service.PatentProposalService;
import com.liuxinlong.modules.system.service.FileManageService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 风险专利实现类
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2024-03-18
 */
@Service
@Slf4j
public class PatentProposalServiceImpl implements PatentProposalService {

    @Autowired
    private PatentProposalDao patentProposalDao;

    @Autowired
    private PatentRiskDao patentRiskDao;

    @Autowired
    private ProjectDao projectDao;

    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private FileManageService fileManageService;

    @Autowired
    private WorkFlowService workFlowService;

    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Autowired
    private WeChatMessageInterface weChatMessageInterface;


    @Override
    public List<Map<String, Object>> pagePatentProposalInfo(Map<String, Object> queryParam) {
        List<PatentProposal> originList = patentProposalDao.pagePatentProposalList(queryParam);
        return completeResult(originList, (int) queryParam.get("startNum"));
    }

    @Override
    public int countPatentProposal(Map<String, Object> queryParam) {
        return patentProposalDao.getPatentProposalCount(queryParam);
    }

    @Override
    public void addPatentProposalInfo(PatentProposal patentProposal) {
        String riskId = patentProposal.getRiskId();
        if (!StringUtils.isEmpty(riskId)) {
            PatentRisk riskInfo = patentRiskDao.selectById(riskId);
            if (ObjectUtils.isEmpty(riskInfo)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "变更点不存在！");
            }
            patentProposal.setProjectId(riskInfo.getProjectId());
            Map<String, Object> queryParam = new HashMap<>();
            queryParam.put("riskId", riskId);
            queryParam.put("openSn", patentProposal.getOpenSn());
            int count = patentProposalDao.getPatentProposalCount(queryParam);
            if (count > 0) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "风险专利已存在，请确认公开号！");
            }
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        String proposalId = SnowFlake.nextIdStr();
        patentProposal.setId(proposalId);
        patentProposal.setMonitor(1);
        patentProposal.setCreateUser(currentUser.getId());
        patentProposal.setCreateTime(currentTime);
        patentProposalDao.insert(patentProposal);
        fileManageService.updateBusinessFile(patentProposal.getThirdReport(), proposalId);
    }

    @Override
    @Transactional
    public void updatePatentProposalInfo(PatentProposal patentProposal, String pushUser) {
        String proposalId = patentProposal.getId();
        PatentProposal oldInfo = patentProposalDao.selectById(proposalId);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "专利风险点不存在！");
        }
        if (patentProposal.getLevel()!= oldInfo.getLevel() && StringUtils.isEmpty(pushUser)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "风险等级变化，必须配置通知用户！");
        }
        String riskId = patentProposal.getRiskId();
        if (!StringUtils.isEmpty(riskId)) {
            PatentRisk riskInfo = patentRiskDao.selectById(riskId);
            if (ObjectUtils.isEmpty(riskInfo)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "变更点不存在！");
            }
            patentProposal.setProjectId(riskInfo.getProjectId());
        } else {
            patentProposal.setRiskId("");
            if (StringUtils.isEmpty(patentProposal.getProjectId())) {
                patentProposal.setProjectId("");
            }
        }
        patentProposal.setCreateUser(oldInfo.getCreateUser());
        patentProposal.setCreateTime(oldInfo.getCreateTime());
        patentProposal.setMonitor(oldInfo.getMonitor());
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        patentProposal.setUpdateUser(currentUser.getId());
        patentProposal.setUpdateTime(currentTime);
        patentProposalDao.updateById(patentProposal);
        fileManageService.updateBusinessFile(patentProposal.getThirdReport(), proposalId);
        if(!StringUtils.isEmpty(pushUser)) {
            String projectId = patentProposal.getProjectId();
            Project projectDto = new Project();
            if (!StringUtils.isEmpty(projectId)) {
                projectDto =  projectDao.selectById(projectId);
            }
            String content = patentProposal.getLevel() == 1 ?
                    "【" + projectDto.getProjectName()+"】项目的【" + patentProposal.getOpenSn() + "】 专利为高风险专利，该项目存在侵权风险！！！" :
//                    "【" + projectDto.getProjectName()+"】项目的【" + patentProposal.getOpenSn() + "】 专利发生风险等级变化，敬请关注!";
            "【" + projectDto.getProjectName()+"】项目的【" + patentProposal.getOpenSn() + "】 专利风险等级由" +
                    PatentRiskLevelTypeEnum.getNameByValue(oldInfo.getLevel()) + "变为"+
                    PatentRiskLevelTypeEnum.getNameByValue(patentProposal.getLevel()) + "，敬请关注!";
            List<String> messageList = Arrays.asList(pushUser.split(","));
            MessageConfiguration messageConfiguration = new MessageConfiguration();
            messageConfiguration.setBusinessType(MessagePushBusinessEnum.PATENT_RISK.getValue());
            messageConfiguration.setContent(content);
            messageConfiguration.setContentType(MessageContentTypeEnum.TEXT_CARD.getValue());
            weChatMessageInterface.pushMessage(messageList, null, messageConfiguration, currentTime);
        }
    }

    @Override
    public void deletePatentProposalInfo(String id) {
        patentProposalDao.deleteById(id);
    }

    @Override
    public void updatePatentProposalStatus(String id, int targetStatus, String remark) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        PatentProposal patentProposal = patentProposalDao.selectById(id);
        if (ObjectUtils.isEmpty(patentProposal)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，原专利信息不存在！");
        }
        patentProposal.setMonitor(targetStatus);
        patentProposal.setRemark(remark);
        patentProposal.setUpdateTime(currentTime);
        patentProposal.setUpdateUser(currentUser.getId());
        patentProposalDao.updateById(patentProposal);
    }

    @Override
    public List<Map<String, Object>> queryPatentProposalList(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "查询失败，设计差异点为空！");
        }
        List<String> riskList = Arrays.asList(id.split(","));
        if (ObjectUtils.isEmpty(riskList)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "查询失败，设计差异点为空！");
        }
        List<PatentProposal> originList = patentProposalDao.queryPatentProposalList(riskList);
        return completeResult(originList, 0);
    }

    @Override
    public ImportResp importPatentProposals(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
//                UserDepartment UserDepartment = covertToBean(record);
                return false;
//				try {
//					UserDepartmentDao.addDetail(UserDepartment);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetMessage("导入风险专利数据部分失败，总数=" + resp.getTotal() + ",失败总数=" + resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入风险专利数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<String[]> recordList = failRecords.stream().sorted(Comparator.comparing((String[] item) -> ((String) item[5]))).collect(Collectors.toList());
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : recordList) {
                    Map item = new HashMap<>();
                    item.put("sort", sort);
                    item.put("openSn", failRecord[1]);
                    item.put("patentName", failRecord[2]);
//                    item.put("patentSn", failRecord[1]);
                    item.put("classType", failRecord[3]);
                    item.put("patentee", failRecord[4]);
                    item.put("status", failRecord[5]);
                    item.put("applyDate", failRecord[6]);
                    item.put("level", failRecord[7]);
                    item.put("rightFalling", failRecord[8]);
                    item.put("handlingPlan", failRecord[9]);
                    item.put("monitor", failRecord[10]);
                    list.add(item);
                    sort++;
                }
//                List<Map> sortList = list.stream().sorted(Comparator.comparing((Map item) -> ((String) item.get("sn")))).collect(Collectors.toList());
                return list;
            }
        });
    }

    @Override
    public ImportResp batchAddPatentProposal(String riskId, List<ImportPatentProposalDto> dataList) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        List<Map> failedList = new ArrayList<>();
        List<PatentProposal> importList = new ArrayList<>();
        String projectId = "";
        boolean riskFlag = false;
        Map<String, PatentProposal> patentProposalMap = new HashMap<>();
        if (!StringUtils.isEmpty(riskId)) {
            riskFlag = true;
            PatentRisk patentRisk = patentRiskDao.selectById(riskId);
            projectId = patentRisk.getProjectId();
            Map<String, Object> queryParam = new HashMap<>();
            queryParam.put("startNum", 0);
            queryParam.put("pageSize", 10000);
            queryParam.put("riskId", riskId);
            List<PatentProposal> dbList = patentProposalDao.pagePatentProposalList(queryParam);
            for (PatentProposal proposal : dbList) {
                patentProposalMap.put(proposal.getOpenSn().trim(), proposal);
            }
        }
        List<PatentProposal> updateList = new ArrayList<>();
        int sort = 1;
        for (ImportPatentProposalDto proposalDto : dataList) {
            PatentProposal patentProposal = new PatentProposal();
            String openSn = proposalDto.getOpenSn().trim();
            if (patentProposalMap.containsKey(openSn)) {
                patentProposal = patentProposalMap.get(openSn);
                patentProposal.setUpdateUser(currentUser.getId());
                patentProposal.setUpdateTime(currentTime);
            } else {
                patentProposal.setId(SnowFlake.nextIdStr());
                patentProposal.setRiskId(riskId);
                patentProposal.setProjectId(projectId);
                patentProposal.setCreateUser(currentUser.getId());
                patentProposal.setCreateTime(currentTime);
            }
            patentProposal.setPatentName(proposalDto.getPatentName());
            patentProposal.setPatentSn(proposalDto.getPatentSn());
            patentProposal.setOpenSn(proposalDto.getOpenSn());
            patentProposal.setClassType(PatentClassTypeEnum.getValueByName(proposalDto.getClassType()));
            patentProposal.setPatentee(proposalDto.getPatentee());
            patentProposal.setStatus(proposalDto.getStatus());
            patentProposal.setApplyDate(proposalDto.getApplyDate());
            patentProposal.setLevel(StringUtils.equals(proposalDto.getLevel(), "高风险") ? 1 :
                    StringUtils.equals(proposalDto.getLevel(), "低风险") ? 2 :
                            StringUtils.equals(proposalDto.getLevel(), "无风险") ? 3 : 0);
//            patentProposal.setRiskType(StringUtils.equals(proposalDto.getStatus(), "侵权") ? 1 : 2);
            patentProposal.setRightFalling(proposalDto.getRightFalling());
            patentProposal.setHandlingPlan(proposalDto.getHandlingPlan());
            patentProposal.setMonitor(StringUtils.equals(proposalDto.getMonitor(), "是") ? 1 : 2);
            if (!patentProposalMap.containsKey(openSn)) {
                importList.add(patentProposal);
                continue;
            }
            updateList.add(patentProposal);
        }
        if (!importList.isEmpty()) {
            patentProposalDao.insertBatch(importList);
        }
        if (!updateList.isEmpty()) {
            patentProposalDao.updateBatchById(updateList);
        }
        ImportResp resp = new ImportResp();
        resp.setRetCode(failedList.size() > 0 ? ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() : ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setRetMessage(failedList.size() > 0 ? "导入风险专利信息部分成功" : "导入风险专利信息成功");
        resp.setFailedList(failedList);
        resp.setTotal(dataList.size());
        resp.setSuccessTotal(importList.size());
        resp.setFailedTotal(failedList.size());
        return resp;
    }

    @Override
    public void exportPatentProposal(Map<String, Object> param, HttpServletResponse response) {
        param.put("startNum", 0);
        param.put("pageSize", 10000);
        List<PatentProposal> originList = patentProposalDao.pagePatentProposalList(param);
        ExcelData data = new ExcelData();
        data.setFileName("风险专利信息导出excel.xlsx");
        String[] head = {"序号", "公开号", "专利名称", "类型", "专利权人", "法律状态", "申请日", "风险分级", "风险分析（落入权项/不具备的特征）", "风险处理方案/过程", "是否监控"};
        data.setHead(head);
        String[][] dataList = new String[originList.size()][head.length];
        int index = 0;
//        Map<String, Map<String, String>> projectMap = projectDao.getProjectMap();
//        Map<String, Map<String, String>> patentRiskMap = patentRiskDao.getPatentRiskMap();
        for (PatentProposal item : originList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = item.getOpenSn();
            dataList[index][2] = item.getPatentName();
            dataList[index][3] = PatentClassTypeEnum.getNameByValue(item.getClassType());
            dataList[index][4] = item.getPatentee();
            dataList[index][5] = item.getStatus();
            dataList[index][6] = item.getApplyDate();
            dataList[index][7] = item.getLevel() == 1 ? "高风险" : item.getLevel() == 2 ? "低风险" : "无风险";
//            dataList[index][8] = item.getRiskType() == 1 ? "侵权" : "不侵权";
            dataList[index][8] = item.getRightFalling();
            dataList[index][9] = item.getHandlingPlan();
            dataList[index][10] = item.getMonitor() == 1 ? "是" : "否";
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public void startWorkflow(String id, String dataString, List<Map<String, Object>> changeList) {
        workFlowService.startWorkflow(id, WorkflowTypeEnum.PATENT_RISK.getValue(), dataString);
    }

    /**
     * 补全数据
     *
     * @param originList 原始数据
     * @param startNum   起始值
     * @return 补全后数据
     */
    private List<Map<String, Object>> completeResult(List<PatentProposal> originList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());
        Map<String, Map<String, String>> projectMap = projectDao.getProjectMap();
        Map<String, Map<String, String>> patentRiskMap = patentRiskDao.getPatentRiskMap();
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        int sort = startNum + 1;
        for (PatentProposal patentProposal : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(patentProposal);
            map.put("sort", sort);
            map.put("classTypeName", PatentClassTypeEnum.getNameByValue(patentProposal.getClassType()));
            map.put("statusName", patentProposal.getStatus());
            map.put("riskTypeName", patentProposal.getRiskType() == 1 ? "侵权" : "不侵权");
            String projectId = patentProposal.getProjectId();
            if (!StringUtils.isEmpty(projectId)) {
                Map<String, String> projectInfo = projectMap.containsKey(projectId) ?
                        projectMap.get(projectId) : new HashMap<>();
                if (!ObjectUtils.isEmpty(projectInfo)) {
                    map.put("projectName", projectInfo.get("name"));
                    int projectType = Integer.parseInt(String.valueOf(projectInfo.get("projectType")));
                    map.put("projectTypeName", projectType == 1 ? "预研项目" : projectType == 2 ? "新品开发" : projectType == 3 ? "其他" : "未知类型");
                    map.put("departmentName", departmentMap.containsKey(projectInfo.get("department")) ? departmentMap.get(projectInfo.get("department")).get("name") : "");
                    int projectLevel = Integer.parseInt(String.valueOf(projectInfo.get("projectLevel")));
                    map.put("projectLevelName", ProjectLevelEnum.getNameByValue(projectLevel));
                }

            }

            map.put("riskName", StringUtils.isEmpty(patentProposal.getRiskId()) ? null :
                    patentRiskMap.containsKey(patentProposal.getRiskId()) ?
                            patentRiskMap.get(patentProposal.getRiskId()).get("name") : null);
            map.put("levelName", patentProposal.getLevel() == 1 ? "高风险" : patentProposal.getLevel() == 2 ? "低风险" : patentProposal.getLevel() == 3 ? "无风险" : "未定义");
            resultList.add(map);
            sort++;
        }
        return resultList;
    }


    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[0].trim())) {
            addRowError("风险专利名称不能为空", rowErrors);
        } else {
            if (record[0].trim().length() > 50) {
                addRowError("风险专利名称长度不能超过20", rowErrors);
            }
        }
//        if (StringUtils.isEmpty(record[1].trim())) {
//            addRowError("部门编码不能为空", rowErrors);
//        } else {
//            if (record[1].trim().length() > 20) {
//                addRowError("部门编码长度不能超过20", rowErrors);
//            }
//        }
//        if (record.length > 2 && !StringUtils.isEmpty(record[2].trim())) {
//            if (record[2].trim().length() > 200) {
//                addRowError("描述长度不能超过200", rowErrors);
//            }
//        }

        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }
}
